package com.kexilo.core.common.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.retry.MessageRecoverer;
import org.springframework.amqp.rabbit.retry.RepublishMessageRecoverer;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.retry.backoff.ExponentialBackOffPolicy;
import org.springframework.retry.policy.SimpleRetryPolicy;
import org.springframework.retry.support.RetryTemplate;

import java.util.Map;

/**
 * RabbitMQ高级配置
 * 提供消息队列的高级功能配置，包括重试、死信队列、延时队列等
 * 
 * @author Kexilo
 */
@Configuration
@ConditionalOnProperty(name = "spring.rabbitmq.enabled", havingValue = "true", matchIfMissing = true)
public class RabbitMQAdvancedConfig {
    
    private static final Logger log = LoggerFactory.getLogger(RabbitMQAdvancedConfig.class);
    
    @Value("${spring.rabbitmq.host:localhost}")
    private String host;
    
    @Value("${spring.rabbitmq.port:5672}")
    private int port;
    
    @Value("${spring.rabbitmq.username:guest}")
    private String username;
    
    @Value("${spring.rabbitmq.password:guest}")
    private String password;
    
    @Value("${spring.rabbitmq.virtual-host:/}")
    private String virtualHost;
    
    // 队列和交换机常量
    public static final String SYSTEM_EXCHANGE = "kexilo.system.exchange";
    public static final String AUDIT_EXCHANGE = "kexilo.audit.exchange";
    public static final String NOTIFICATION_EXCHANGE = "kexilo.notification.exchange";
    public static final String DELAY_EXCHANGE = "kexilo.delay.exchange";
    
    // 队列名称
    public static final String USER_OPERATION_QUEUE = "kexilo.user.operation.queue";
    public static final String AUDIT_LOG_QUEUE = "kexilo.audit.log.queue";
    public static final String EMAIL_NOTIFICATION_QUEUE = "kexilo.email.notification.queue";
    public static final String SMS_NOTIFICATION_QUEUE = "kexilo.sms.notification.queue";
    public static final String DELAY_QUEUE = "kexilo.delay.queue";
    
    // 死信队列
    public static final String DLX_EXCHANGE = "kexilo.dlx.exchange";
    public static final String DLQ_QUEUE = "kexilo.dlq.queue";
    
    // 路由键
    public static final String USER_CREATE_ROUTING_KEY = "user.create";
    public static final String USER_UPDATE_ROUTING_KEY = "user.update";
    public static final String USER_DELETE_ROUTING_KEY = "user.delete";
    public static final String AUDIT_LOG_ROUTING_KEY = "audit.log";
    public static final String EMAIL_ROUTING_KEY = "notification.email";
    public static final String SMS_ROUTING_KEY = "notification.sms";
    
    /**
     * 连接工厂配置
     */
    @Bean
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory factory = new CachingConnectionFactory();
        factory.setHost(host);
        factory.setPort(port);
        factory.setUsername(username);
        factory.setPassword(password);
        factory.setVirtualHost(virtualHost);
        
        // 连接池配置
        factory.setChannelCacheSize(50);
        factory.setConnectionCacheSize(10);
        factory.setChannelCheckoutTimeout(30000);
        
        // 连接超时配置
        factory.setConnectionTimeout(30000);
        factory.setRequestedHeartBeat(60);
        
        // 发布确认
        factory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED);
        factory.setPublisherReturns(true);
        
        log.info("RabbitMQ连接工厂配置完成 - Host: {}, Port: {}", host, port);
        return factory;
    }
    
    /**
     * RabbitTemplate配置
     */
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        
        // 消息转换器
        template.setMessageConverter(messageConverter());
        
        // 强制消息路由
        template.setMandatory(true);
        
        // 发布确认回调
        template.setConfirmCallback((correlationData, ack, cause) -> {
            if (ack) {
                log.debug("消息发送确认成功: {}", correlationData);
            } else {
                log.error("消息发送确认失败: {}, 原因: {}", correlationData, cause);
            }
        });
        
        // 消息返回回调
        template.setReturnsCallback(returned -> {
            log.error("消息返回: Exchange={}, RoutingKey={}, Message={}", 
                     returned.getExchange(), returned.getRoutingKey(), returned.getMessage());
        });
        
        // 重试模板
        template.setRetryTemplate(retryTemplate());
        
        log.info("RabbitTemplate配置完成");
        return template;
    }
    
    /**
     * 消息转换器
     */
    @Bean
    public MessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }
    
    /**
     * 重试模板
     */
    @Bean
    public RetryTemplate retryTemplate() {
        RetryTemplate retryTemplate = new RetryTemplate();
        
        // 重试策略
        SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
        retryPolicy.setMaxAttempts(3);
        retryTemplate.setRetryPolicy(retryPolicy);
        
        // 退避策略
        ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
        backOffPolicy.setInitialInterval(1000);
        backOffPolicy.setMultiplier(2.0);
        backOffPolicy.setMaxInterval(10000);
        retryTemplate.setBackOffPolicy(backOffPolicy);
        
        return retryTemplate;
    }
    
    /**
     * 监听器容器工厂
     */
    @Bean
    public RabbitListenerContainerFactory<?> rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setMessageConverter(messageConverter());
        
        // 并发配置
        factory.setConcurrentConsumers(2);
        factory.setMaxConcurrentConsumers(10);
        
        // 预取配置
        factory.setPrefetchCount(10);
        
        // 确认模式
        factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
        
        // 重试配置
        factory.setRetryTemplate(retryTemplate());
        
        log.info("RabbitMQ监听器容器工厂配置完成");
        return factory;
    }
    
    /**
     * 系统交换机
     */
    @Bean
    public TopicExchange systemExchange() {
        return ExchangeBuilder
                .topicExchange(SYSTEM_EXCHANGE)
                .durable(true)
                .build();
    }
    
    /**
     * 审计交换机
     */
    @Bean
    public TopicExchange auditExchange() {
        return ExchangeBuilder
                .topicExchange(AUDIT_EXCHANGE)
                .durable(true)
                .build();
    }
    
    /**
     * 通知交换机
     */
    @Bean
    public TopicExchange notificationExchange() {
        return ExchangeBuilder
                .topicExchange(NOTIFICATION_EXCHANGE)
                .durable(true)
                .build();
    }
    
    /**
     * 延时交换机
     */
    @Bean
    public CustomExchange delayExchange() {
        return new CustomExchange(DELAY_EXCHANGE, "x-delayed-message", true, false,
                Map.of("x-delayed-type", "topic"));
    }
    
    /**
     * 死信交换机
     */
    @Bean
    public DirectExchange deadLetterExchange() {
        return ExchangeBuilder
                .directExchange(DLX_EXCHANGE)
                .durable(true)
                .build();
    }
    
    /**
     * 用户操作队列
     */
    @Bean
    public Queue userOperationQueue() {
        return QueueBuilder
                .durable(USER_OPERATION_QUEUE)
                .withArgument("x-dead-letter-exchange", DLX_EXCHANGE)
                .withArgument("x-dead-letter-routing-key", "dlq")
                .withArgument("x-message-ttl", 300000) // 5分钟TTL
                .build();
    }
    
    /**
     * 审计日志队列
     */
    @Bean
    public Queue auditLogQueue() {
        return QueueBuilder
                .durable(AUDIT_LOG_QUEUE)
                .withArgument("x-dead-letter-exchange", DLX_EXCHANGE)
                .withArgument("x-dead-letter-routing-key", "dlq")
                .build();
    }
    
    /**
     * 邮件通知队列
     */
    @Bean
    public Queue emailNotificationQueue() {
        return QueueBuilder
                .durable(EMAIL_NOTIFICATION_QUEUE)
                .withArgument("x-dead-letter-exchange", DLX_EXCHANGE)
                .withArgument("x-dead-letter-routing-key", "dlq")
                .withArgument("x-max-retries", 3)
                .build();
    }
    
    /**
     * 短信通知队列
     */
    @Bean
    public Queue smsNotificationQueue() {
        return QueueBuilder
                .durable(SMS_NOTIFICATION_QUEUE)
                .withArgument("x-dead-letter-exchange", DLX_EXCHANGE)
                .withArgument("x-dead-letter-routing-key", "dlq")
                .withArgument("x-max-retries", 3)
                .build();
    }
    
    /**
     * 延时队列
     */
    @Bean
    public Queue delayQueue() {
        return QueueBuilder
                .durable(DELAY_QUEUE)
                .build();
    }
    
    /**
     * 死信队列
     */
    @Bean
    public Queue deadLetterQueue() {
        return QueueBuilder
                .durable(DLQ_QUEUE)
                .build();
    }
    
    /**
     * 绑定用户操作队列到系统交换机
     */
    @Bean
    public Binding userOperationBinding() {
        return BindingBuilder
                .bind(userOperationQueue())
                .to(systemExchange())
                .with("user.*");
    }
    
    /**
     * 绑定审计日志队列到审计交换机
     */
    @Bean
    public Binding auditLogBinding() {
        return BindingBuilder
                .bind(auditLogQueue())
                .to(auditExchange())
                .with(AUDIT_LOG_ROUTING_KEY);
    }
    
    /**
     * 绑定邮件通知队列到通知交换机
     */
    @Bean
    public Binding emailNotificationBinding() {
        return BindingBuilder
                .bind(emailNotificationQueue())
                .to(notificationExchange())
                .with(EMAIL_ROUTING_KEY);
    }
    
    /**
     * 绑定短信通知队列到通知交换机
     */
    @Bean
    public Binding smsNotificationBinding() {
        return BindingBuilder
                .bind(smsNotificationQueue())
                .to(notificationExchange())
                .with(SMS_ROUTING_KEY);
    }
    
    /**
     * 绑定延时队列到延时交换机
     */
    @Bean
    public Binding delayBinding() {
        return BindingBuilder
                .bind(delayQueue())
                .to(delayExchange())
                .with("delay.*")
                .noargs();
    }
    
    /**
     * 绑定死信队列到死信交换机
     */
    @Bean
    public Binding deadLetterBinding() {
        return BindingBuilder
                .bind(deadLetterQueue())
                .to(deadLetterExchange())
                .with("dlq");
    }
    
    /**
     * 消息恢复器（用于处理重试失败的消息）
     */
    @Bean
    public MessageRecoverer messageRecoverer(RabbitTemplate rabbitTemplate) {
        return new RepublishMessageRecoverer(rabbitTemplate, DLX_EXCHANGE, "dlq");
    }
}
